# -*- coding:utf-8 -*-
import websocket
import datetime
import hashlib
import base64
import hmac
import json
from urllib.parse import urlencode
import time
import ssl
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import _thread as thread

STATUS_FIRST_FRAME = 0  
STATUS_CONTINUE_FRAME = 1  
STATUS_LAST_FRAME = 2  


class Ws_Param(object):
    
    def __init__(self, APPID, APIKey, APISecret, AudioFile):
        self.APPID = APPID
        self.APIKey = APIKey
        self.APISecret = APISecret
        self.AudioFile = AudioFile

       
        self.CommonArgs = {"app_id": self.APPID}
       
        self.BusinessArgs = {
            "domain": "iat",
            "language": "zh_cn",
            "accent": "mandarin",
            "vinfo": 1,
            "vad_eos": 10000,
        }

 
    def create_url(self):
        url = "wss://ws-api.xfyun.cn/v2/iat"
     
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))

       
        signature_origin = "host: " + "ws-api.xfyun.cn" + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + "/v2/iat " + "HTTP/1.1"
       
        signature_sha = hmac.new(
            self.APISecret.encode("utf-8"),
            signature_origin.encode("utf-8"),
            digestmod=hashlib.sha256,
        ).digest()
        signature_sha = base64.b64encode(signature_sha).decode(encoding="utf-8")

        authorization_origin = (
            'api_key="%s", algorithm="%s", headers="%s", signature="%s"'
            % (self.APIKey, "hmac-sha256", "host date request-line", signature_sha)
        )
        authorization = base64.b64encode(authorization_origin.encode("utf-8")).decode(
            encoding="utf-8"
        )

        v = {"authorization": authorization, "date": date, "host": "ws-api.xfyun.cn"}
      
        url = url + "?" + urlencode(v)
        return url


class XunfeiSpeechRecognizer:
    def __init__(self, APPID, APIKey, APISecret, AudioFile):
        self.APPID = APPID
        self.APIKey = APIKey
        self.APISecret = APISecret
        self.AudioFile = AudioFile
        self.result = ""

    def recognize(self):
        wsParam = Ws_Param(
            APPID=self.APPID,
            APISecret=self.APISecret,
            APIKey=self.APIKey,
            AudioFile=self.AudioFile,
        )

        def on_message(ws, message):
            try:
                code = json.loads(message)["code"]
                sid = json.loads(message)["sid"]
                if code != 0:
                    errMsg = json.loads(message)["message"]
                    print("sid:%s call error:%s code is:%s" % (sid, errMsg, code))
                else:
                    data = json.loads(message)["data"]["result"]["ws"]
                    result = ""
                    for i in data:
                        for w in i["cw"]:
                            result += w["w"]
                    self.result += result 
            except Exception as e:
                print("receive msg,but parse exception:", e)


        def on_error(ws, error):
            print("### error:", error)

       
        def on_close(ws, a, b):
            print("### closed ###")

      
        def on_open(ws):
            def run(*args):
                frameSize = 8000  
                intervel = 0.04 
                status = STATUS_FIRST_FRAME 

                with open(wsParam.AudioFile, "rb") as fp:
                    while True:
                        buf = fp.read(frameSize)
                       
                        if not buf:
                            status = STATUS_LAST_FRAME
                        
                      
                       
                        if status == STATUS_FIRST_FRAME:
                            d = {
                                "common": wsParam.CommonArgs,
                                "business": wsParam.BusinessArgs,
                                "data": {
                                    "status": 0,
                                    "format": "audio/L16;rate=16000",
                                    "audio": str(base64.b64encode(buf), "utf-8"),
                                    "encoding": "raw",
                                },
                            }
                            d = json.dumps(d)
                            ws.send(d)
                            status = STATUS_CONTINUE_FRAME
                        
                        elif status == STATUS_CONTINUE_FRAME:
                            d = {
                                "data": {
                                    "status": 1,
                                    "format": "audio/L16;rate=16000",
                                    "audio": str(base64.b64encode(buf), "utf-8"),
                                    "encoding": "raw",
                                }
                            }
                            ws.send(json.dumps(d))
                       
                        elif status == STATUS_LAST_FRAME:
                            d = {
                                "data": {
                                    "status": 2,
                                    "format": "audio/L16;rate=16000",
                                    "audio": str(base64.b64encode(buf), "utf-8"),
                                    "encoding": "raw",
                                }
                            }
                            ws.send(json.dumps(d))
                            time.sleep(1)
                            break
                        
                        time.sleep(intervel)
                ws.close()

            thread.start_new_thread(run, ())

        websocket.enableTrace(False)
        wsUrl = wsParam.create_url()
        ws = websocket.WebSocketApp(
            wsUrl,
            on_message=on_message,
            on_error=on_error,
            on_close=on_close,
            on_open=on_open,
        )
        ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
        return self.result


if __name__ == "__main__":
    recognizer = XunfeiSpeechRecognizer(
        APPID="4c8660b2",
        APIKey="b9883ee83a51f75ebd16cd85212de3fa",
        APISecret="MTdhMGU3Mzg3MDYxNDYyZjdkYjA1MTAw",
        AudioFile="./h1.wav",
    )
    result = recognizer.recognize()
    print(result)
